/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
 */

#include "hellovk.h"
#include "fif.h"
#include <set>
#include <unordered_set>
#include <log.hpp>
#include <AAssetImporter.h>
#include <DescriptorPool.h>
#include <CommandPool.h>
#include <Utils.h>
#include <cstdio>
#include <cstring>

bool vkt::HelloVK::ENABLE_EXTRAPOLATION = false;
namespace vkt {
namespace {
// 静态标志，用于控制高频操作的日志输出
static bool s_loggedWaitForFences = false;
static bool s_loggedResetFences = false;
static bool s_loggedResetCommandPool = false;
static bool s_loggedAcquireNextImage = false;
static bool s_loggedBeginCommandBuffer = false;
static bool s_loggedEndCommandBuffer = false;
static bool s_loggedQueueSubmit = false;
static bool s_loggedQueuePresent = false;

[[nodiscard]] const char *ToStringMessageSeverity(VkDebugUtilsMessageSeverityFlagBitsEXT s)
{
    switch (s) {
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
            return "VERBOSE";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
            return "ERROR";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
            return "WARNING";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
            return "INFO";
        default:
            return "UNKNOWN";
    }
}

[[nodiscard]] const char *ToStringMessageType(VkDebugUtilsMessageTypeFlagsEXT s)
{
    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "General | Validation | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "Validation | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "General | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)) {
        return "General | Validation";
    }

    if (s == VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
        return "Validation";
    }

    if (s == VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
        return "General";
    }

    return "Unknown";
}

VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
    VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
    void * /* pUserData */)
{
    static std::unordered_set<uint32_t> const validationFilter{ // Unspecified message. Safe to ignore it.
        0x00000000U, 0x675DC32EU
    };

    auto const messageID = static_cast<uint32_t>(pCallbackData->messageIdNumber);
    if (validationFilter.contains(messageID)) {
        return VK_FALSE;
    }

    auto ms = ToStringMessageSeverity(messageSeverity);
    auto mt = ToStringMessageType(messageType);
    GOLOGI("[%s: %s]\n%s\n", ms, mt, pCallbackData->pMessage);

    return VK_FALSE;
}

void PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo)
{
    constexpr static VkValidationFeatureEnableEXT const validationFeatures[] = {
        VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
        VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT
    };

    constexpr static VkValidationFeaturesEXT validationInfo {
        .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
        .pNext = nullptr,
        .enabledValidationFeatureCount = static_cast<uint32_t>(std::size(validationFeatures)),
        .pEnabledValidationFeatures = validationFeatures,
        .disabledValidationFeatureCount = 0U,
        .pDisabledValidationFeatures = nullptr
    };

    createInfo = {};
    createInfo.pNext = &validationInfo;
    createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;

    createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;

    createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;

    createInfo.pfnUserCallback = &DebugCallback;
}

// [[nodiscard]] VkResult CreateDebugUtilsMessengerEXT(VkInstance instance,
//     const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator,
//     VkDebugUtilsMessengerEXT *pDebugMessenger)
// {
//     auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
//     if (func != nullptr) {
//         return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
//     }

//     return VK_ERROR_EXTENSION_NOT_PRESENT;
// }

// void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger,
//     const VkAllocationCallbacks *pAllocator)
// {
//     auto func = (PFN_vkDestroyDebugUtilsMessenger_EXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
//     if (func != nullptr) {
//         func(instance, debugMessenger, pAllocator);
//     }
// }

glm::mat4 ConvertGLMMat4ToMat4(glm::mat4 matrix)
{
    // 直接返回glm矩阵，不再需要转换
    return matrix;
}

/**
 * GetPrerotationMatrix handles screen rotation with 3 hardcoded rotation
 * matrices (detailed below). We skip the 180 degrees rotation.
 */
void GetPrerotationMatrix(const VkSurfaceCapabilitiesKHR &capabilities,
    const VkSurfaceTransformFlagBitsKHR &pretransformFlag, std::array<float, 16> &mat)
{
    // mat is initialized to the identity matrix
    mat = { 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
    if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
        // mat is set to a 90 deg rotation matrix
        mat = { 0., 1., 0., 0., -1., 0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
        return;
    }

    if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
        // mat is set to 270 deg rotation matrix
        mat = { 0., -1., 0., 0., 1., 0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
    }
}
} // end of anonymous namespace

void HelloVK::InitVulkan()
{
    CreateInstance();
    CreateSurface();
    PickPhysicalDevice();
    CreateLogicalDeviceAndQueue();
    SetupDebugMessenger();
    EstablishDisplaySizeIdentity();
    CreateSwapChain();
    CreateImageViews();
    FGInitDevice();
    FGCreateCommandPool();
    FGCreateColorResources();
    FGCreateDepthResources();
    OHTestApp::DescriptorPool::Instance().Init();
    FGCreateSwapchainSyncObjects();
    FGInitMainSceneRenderer();

    m_initialized = true;
}

void HelloVK::Reset(OHNativeWindow *newWindow, NativeResourceManager *newManager)
{
    m_window.reset(newWindow);
    m_assetManager = newManager;
    OHTestApp::AAssetImporter::Instance().Init(newManager);

    if (m_initialized) {
        CreateSurface();
        RecreateSwapChain();
    }
}

void HelloVK::RecreateSwapChain()
{
    VkResult result = vkDeviceWaitIdle(m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkDeviceWaitIdle completed successfully");
    } else {
        GOLOGE("vkDeviceWaitIdle failed with error: %d", result);
    }
    CleanupSwapChain();
    CreateSwapChain();
    CreateImageViews();
    FGCreateDepthResources();
    FGCreateSwapchainSyncObjects();

    FGDestroyColorResources();
    FGCreateColorResources();
    FGDestroyMainSceneRenderer();
    FGInitMainSceneRenderer();
}

void HelloVK::Render()
{
    
    FGBalancedInterRender();
}

void HelloVK::OnOrientationChange()
{
    RecreateSwapChain();
    m_orientationChanged = false;
}

void HelloVK::CleanupSwapChain()
{
    m_sceneDepthStencil.Destroy();

    for (auto const &info : m_swapchainInfo) {
        if (info.renderEnd != VK_NULL_HANDLE) {
            GOLOGD("Destroying renderEnd semaphore");
            vkDestroySemaphore(m_device, info.renderEnd, nullptr);
            GOLOGW("vkDestroySemaphore completed successfully");
        }
    }

    m_swapchainInfo.clear();

    if (m_sceneFramebuffer != VK_NULL_HANDLE) {
        GOLOGD("Destroying framebuffer");
        vkDestroyFramebuffer(m_device, m_sceneFramebuffer, nullptr);
        GOLOGW("vkDestroyFramebuffer completed successfully");
        m_sceneFramebuffer = VK_NULL_HANDLE;
    }

    for (size_t i = 0; i < m_swapChainImageViews.size(); i++) {
        GOLOGD("Destroying image view %zu", i);
        vkDestroyImageView(m_device, m_swapChainImageViews[i], nullptr);
        GOLOGW("vkDestroyImageView completed successfully");
    }

    GOLOGD("Destroying swapchain");
    vkDestroySwapchainKHR(m_device, m_swapChain, nullptr);
    GOLOGW("vkDestroySwapchainKHR completed successfully");
}

void HelloVK::Cleanup()
{
    VkResult result = vkDeviceWaitIdle(m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkDeviceWaitIdle completed successfully");
    } else {
        GOLOGE("vkDeviceWaitIdle failed with error: %d", result);
    }
    CleanupSwapChain();

    for (auto &info : m_framesInFlights) {
        if (info.commandPool != VK_NULL_HANDLE) {
            GOLOGD("Destroying command pool");
            vkDestroyCommandPool(m_device, info.commandPool, nullptr);
            GOLOGW("vkDestroyCommandPool completed successfully");
        }

        if (info.fence != VK_NULL_HANDLE) {
            GOLOGD("Destroying fence");
            vkDestroyFence(m_device, info.fence, nullptr);
            GOLOGW("vkDestroyFence completed successfully");
        }

        if (info.acquire != VK_NULL_HANDLE) {
            GOLOGD("Destroying acquire semaphore");
            vkDestroySemaphore(m_device, info.acquire, nullptr);
            GOLOGW("vkDestroySemaphore completed successfully");
        }
    }

    m_framesInFlights.clear();

    GOLOGD("Destroying device");
    vkDestroyDevice(m_device, nullptr);
    GOLOGW("vkDestroyDevice completed successfully");

    GOLOGD("Destroying surface");
    vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
    GOLOGW("vkDestroySurfaceKHR completed successfully");
    
    GOLOGD("Destroying instance");
    vkDestroyInstance(m_instance, nullptr);
    GOLOGW("vkDestroyInstance completed successfully");
    m_initialized = false;
}

void HelloVK::SetupDebugMessenger()
{
    if (!ENABLE_VALIDATION_LAYERS) {
        return;
    }
    
}

bool HelloVK::CheckValidationLayerSupport()
{
    uint32_t layerCount;
    VkResult result = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateInstanceLayerProperties (count) completed successfully");
    } else {
        GOLOGE("vkEnumerateInstanceLayerProperties (count) failed with error: %d", result);
        return false;
    }

    std::vector<VkLayerProperties> availableLayers(layerCount);
    result = vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateInstanceLayerProperties (data) completed successfully");
    } else {
        GOLOGE("vkEnumerateInstanceLayerProperties (data) failed with error: %d", result);
        return false;
    }

    for (const char *layerName : m_validationLayers) {
        bool layerFound = false;
        for (const auto &layerProperties : availableLayers) {
            GOLOGI("Avalible %s", layerProperties.layerName);
            if (strcmp(layerName, layerProperties.layerName) == 0) {
                layerFound = true;
                break;
            }
        }

        if (!layerFound) {
            return false;
        }
    }

    return true;
}

std::vector<const char *> HelloVK::GetRequiredExtensions(bool enableValidationLayers)
{
    std::vector<const char *> extensions = { VK_KHR_SURFACE_EXTENSION_NAME, VK_OHOS_SURFACE_EXTENSION_NAME };

    if (enableValidationLayers) {
        extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
    }

    return extensions;
}

void HelloVK::CreateInstance()
{
    // validation layers requested, but not available!
    if (ENABLE_VALIDATION_LAYERS && !CheckValidationLayerSupport()) {
        GOLOGE("Validation layers are unavailable");
        return;
    }
    auto requiredExtensions = GetRequiredExtensions(ENABLE_VALIDATION_LAYERS);

    VkApplicationInfo appInfo{};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = "Hello Triangle";
    appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.pEngineName = "No Engine";
    appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.apiVersion = VK_API_VERSION_1_3;

    VkInstanceCreateInfo createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    createInfo.pApplicationInfo = &appInfo;
    createInfo.enabledExtensionCount = (uint32_t)requiredExtensions.size();
    createInfo.ppEnabledExtensionNames = requiredExtensions.data();
    createInfo.pApplicationInfo = &appInfo;
    

    VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateInstance completed successfully");
    } else {
        GOLOGE("vkCreateInstance failed with error: %d", result);
        return;
    }

    if (ENABLE_VALIDATION_LAYERS) {
//        OHTestApp::SetupDebugLabels(m_instance);
    }

    uint32_t extensionCount = 0;
    result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateInstanceExtensionProperties (count) completed successfully");
    } else {
        GOLOGE("vkEnumerateInstanceExtensionProperties (count) failed with error: %d", result);
    }
    
    std::vector<VkExtensionProperties> extensions(extensionCount);
    result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateInstanceExtensionProperties (data) completed successfully");
    } else {
        GOLOGE("vkEnumerateInstanceExtensionProperties (data) failed with error: %d", result);
    }
}

/*
 * CreateSurface can only be called after the ohos ecosystem has had the
 * chance to provide a native window. This happens after the APP_CMD_START event
 * has had a chance to be called.
 *
 * Notice the window.get() call which is only valid after window has been set to
 * a non null value
 */
void HelloVK::CreateSurface()
{
    if (!m_window) {
        GOLOGE("window not initialized");
        return;
    }

    const VkSurfaceCreateInfoOHOS create_info {
        .sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS,
        .pNext = nullptr,
        .flags = 0,
        .window = m_window.get()
    };

    VkResult result = vkCreateSurfaceOHOS(m_instance, &create_info, nullptr, &m_surface);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateSurfaceOHOS completed successfully");
    } else {
        GOLOGE("vkCreateSurfaceOHOS failed with error: %d", result);
    }
}

// BEGIN DEVICE SUITABILITY
// Functions to find a suitable physical device to execute Vulkan commands.

QueueFamilyIndices HelloVK::FindQueueFamilies(VkPhysicalDevice device)
{
    QueueFamilyIndices indices;

    uint32_t queueFamilyCount = 0;
    vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
    GOLOGW("vkGetPhysicalDeviceQueueFamilyProperties (count) completed successfully");

    std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
    vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
    GOLOGW("vkGetPhysicalDeviceQueueFamilyProperties (data) completed successfully");

    int i = 0;
    for (const auto &queueFamily : queueFamilies) {
        if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            indices.graphicsFamily = i;
        }

        VkBool32 presentSupport = false;
        VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_surface, &presentSupport);
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfaceSupportKHR completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfaceSupportKHR failed with error: %d", result);
        }
        
        if (presentSupport) {
            indices.presentFamily = i;
        }

        if (indices.isComplete()) {
            break;
        }

        ++i;
    }
    return indices;
}

bool HelloVK::CheckDeviceExtensionSupport(VkPhysicalDevice device)
{
    uint32_t extensionCount;
    VkResult result = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateDeviceExtensionProperties (count) completed successfully");
    } else {
        GOLOGE("vkEnumerateDeviceExtensionProperties (count) failed with error: %d", result);
        return false;
    }

    std::vector<VkExtensionProperties> availableExtensions(extensionCount);
    result = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateDeviceExtensionProperties (data) completed successfully");
    } else {
        GOLOGE("vkEnumerateDeviceExtensionProperties (data) failed with error: %d", result);
        return false;
    }

    std::set<std::string> requiredExtensions(m_deviceExtensions.begin(), m_deviceExtensions.end());

    for (const auto &extension : availableExtensions) {
        requiredExtensions.erase(extension.extensionName);
    }
    

    return requiredExtensions.empty();
}

SwapChainSupportDetails HelloVK::QuerySwapChainSupport(VkPhysicalDevice device)
{
    SwapChainSupportDetails details;

    VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &details.capabilities);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceCapabilitiesKHR completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed with error: %d", result);
    }

    uint32_t formatCount;
    result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceFormatsKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceFormatsKHR (count) failed with error: %d", result);
    }

    if (formatCount != 0) {
        details.formats.resize(formatCount);
        result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, details.formats.data());
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfaceFormatsKHR (data) completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfaceFormatsKHR (data) failed with error: %d", result);
        }
    }

    uint32_t presentModeCount;
    result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfacePresentModesKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfacePresentModesKHR (count) failed with error: %d", result);
    }

    if (presentModeCount != 0) {
        details.presentModes.resize(presentModeCount);
        result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, details.presentModes.data());
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfacePresentModesKHR (data) completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfacePresentModesKHR (data) failed with error: %d", result);
        }
    }
    return details;
}

bool HelloVK::IsDeviceSuitable(VkPhysicalDevice device)
{
    QueueFamilyIndices indices = FindQueueFamilies(device);
    bool extensionsSupported = CheckDeviceExtensionSupport(device);
    bool swapChainAdequate = false;
    if (extensionsSupported) {
        SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(device);
        swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
    }

    return indices.isComplete() && extensionsSupported && swapChainAdequate;
}

void HelloVK::PickPhysicalDevice()
{
    uint32_t deviceCount = 0;
    VkResult result = vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumeratePhysicalDevices (count) completed successfully");
    } else {
        GOLOGE("vkEnumeratePhysicalDevices (count) failed with error: %d", result);
        return;
    }

    if (deviceCount <= 0) {
        GOLOGE("failed to find GPUs with Vulkan support!");
        return;
    }

    std::vector<VkPhysicalDevice> devices(deviceCount);
    result = vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumeratePhysicalDevices (data) completed successfully");
    } else {
        GOLOGE("vkEnumeratePhysicalDevices (data) failed with error: %d", result);
        return;
    }

    for (const auto &device : devices) {
        if (IsDeviceSuitable(device)) {
            m_physicalDevice = device;
            break;
        }
    }

    if (m_physicalDevice == VK_NULL_HANDLE) {
        GOLOGE("failed to find a suitable GPU!");
        return;
    }

    vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_physicalDeviceFeatures);
    GOLOGW("vkGetPhysicalDeviceFeatures completed successfully");
    
    vkGetPhysicalDeviceProperties(m_physicalDevice, &m_physicalDeviceProperties);
    GOLOGW("vkGetPhysicalDeviceProperties completed successfully");
}
// END DEVICE SUITABILITY

void HelloVK::CreateLogicalDeviceAndQueue()
{
    QueueFamilyIndices indices = FindQueueFamilies(m_physicalDevice);
    std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
    std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
    float queuePriority = 1.0F;
    for (uint32_t queueFamily : uniqueQueueFamilies) {
        VkDeviceQueueCreateInfo queueCreateInfo{};
        queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queueCreateInfo.queueFamilyIndex = queueFamily;
        queueCreateInfo.queueCount = 1;
        queueCreateInfo.pQueuePriorities = &queuePriority;
        queueCreateInfos.push_back(queueCreateInfo);
    }

    VkDeviceCreateInfo createInfo{};
    VkPhysicalDeviceFeatures deviceFeatures{};
    VkPhysicalDeviceFloat16Int8FeaturesKHR float16Int8Features{};
    float16Int8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
    float16Int8Features.pNext = nullptr;
    float16Int8Features.shaderFloat16 = VK_TRUE;
    float16Int8Features.shaderInt8 = VK_FALSE;
    createInfo.pNext = &float16Int8Features;

    deviceFeatures.samplerAnisotropy = m_physicalDeviceFeatures.samplerAnisotropy;
    deviceFeatures.shaderInt16 = VK_TRUE;
    deviceFeatures.fragmentStoresAndAtomics = VK_TRUE;

    createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
    createInfo.pQueueCreateInfos = queueCreateInfos.data();
    createInfo.pEnabledFeatures = &deviceFeatures;
    createInfo.enabledExtensionCount = static_cast<uint32_t>(m_deviceExtensions.size());
    createInfo.ppEnabledExtensionNames = m_deviceExtensions.data();

    VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateDevice completed successfully");
    } else {
        GOLOGE("vkCreateDevice failed with error: %d", result);
        return;
    }

    vkGetDeviceQueue(m_device, indices.graphicsFamily.value(), 0, &m_graphicsQueue);
    GOLOGW("vkGetDeviceQueue (graphics) completed successfully");
    
    vkGetDeviceQueue(m_device, indices.presentFamily.value(), 0, &m_presentQueue);
    GOLOGW("vkGetDeviceQueue (present) completed successfully");
}

void HelloVK::EstablishDisplaySizeIdentity()
{
    VkSurfaceCapabilitiesKHR capabilities;
    VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceCapabilitiesKHR completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed with error: %d", result);
        return;
    }

    float ratio;
    if (capabilities.currentExtent.width < capabilities.currentExtent.height) {
        ratio = static_cast<float>(capabilities.currentExtent.width) / m_resolution;
    } else {
        ratio = static_cast<float>(capabilities.currentExtent.height) / m_resolution;
    }
    capabilities.currentExtent.width = static_cast<uint32_t>(capabilities.currentExtent.width / ratio);
    capabilities.currentExtent.height = static_cast<uint32_t>(capabilities.currentExtent.height / ratio);

    m_displaySizeIdentity = capabilities.currentExtent;
}

void HelloVK::ExecuteCreateSwapChain(VkSwapchainCreateInfoKHR &createInfo, uint32_t imageCount, VkFormat format)
{
    VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapChain);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateSwapchainKHR completed successfully");
    } else {
        GOLOGE("vkCreateSwapchainKHR failed with error: %d", result);
        return;
    }
    
    result = vkGetSwapchainImagesKHR(m_device, m_swapChain, &imageCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetSwapchainImagesKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetSwapchainImagesKHR (count) failed with error: %d", result);
    }
    
    m_swapChainImages.resize(imageCount);
    result = vkGetSwapchainImagesKHR(m_device, m_swapChain, &imageCount, m_swapChainImages.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetSwapchainImagesKHR (data) completed successfully");
    } else {
        GOLOGE("vkGetSwapchainImagesKHR (data) failed with error: %d", result);
    }

    for (uint32_t i = 0U; i < imageCount; ++i) {
        char label[256U];
        
        // 使用安全的 snprintf 替换 snprintf_s
        int iRet = std::snprintf(label, sizeof(label), "Swapchain image #%u", i);
        if (iRet < 0 || static_cast<size_t>(iRet) >= sizeof(label)) {
            // 格式化失败或缓冲区不足，使用默认标签
            std::strncpy(label, "Swapchain image", sizeof(label) - 1);
            label[sizeof(label) - 1] = '\0';  // 确保以null结尾
            GOLOGE("snprintf failed or buffer too small for swapchain image #%u", i);
        }
        
        OHTestApp::SetLabel(m_device, m_swapChainImages[i], VK_OBJECT_TYPE_IMAGE, label);
    }

    m_swapChainImageFormat = format;
    m_swapChainExtent = m_displaySizeIdentity;
    GOLOGI("create swapchain image count: %u", imageCount);
}

void HelloVK::CreateSwapChain()
{
    SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(m_physicalDevice);

    auto chooseSwapSurfaceFormat = [](const std::vector<VkSurfaceFormatKHR> &availableFormats) {
        for (const auto &availableFormat : availableFormats) {
            if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB &&
                availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
                return availableFormat;
            }
        }

        return availableFormats[0];
    };

    VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);

    VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;

    uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
    if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
        imageCount = swapChainSupport.capabilities.maxImageCount;
    }
    GOLOGI("minSwapchain image count: %u request: %u", swapChainSupport.capabilities.minImageCount, imageCount);
    m_pretransformFlag = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;

    VkSwapchainCreateInfoKHR createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    createInfo.surface = m_surface;
    createInfo.minImageCount = imageCount;
    createInfo.imageFormat = surfaceFormat.format;
    createInfo.imageColorSpace = surfaceFormat.colorSpace;
    createInfo.imageExtent = m_displaySizeIdentity;
    createInfo.imageArrayLayers = 1;

    createInfo.imageUsage =
        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

    createInfo.preTransform = m_pretransformFlag;

    QueueFamilyIndices indices = FindQueueFamilies(m_physicalDevice);
    uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()};

    if (indices.graphicsFamily != indices.presentFamily) {
        createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
        createInfo.queueFamilyIndexCount = 2U;
        createInfo.pQueueFamilyIndices = queueFamilyIndices;
    } else {
        createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
        createInfo.queueFamilyIndexCount = 0U;
        createInfo.pQueueFamilyIndices = nullptr;
    }

    createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
    createInfo.presentMode = presentMode;
    createInfo.clipped = VK_TRUE;
    createInfo.oldSwapchain = VK_NULL_HANDLE;

    ExecuteCreateSwapChain(createInfo, imageCount, surfaceFormat.format);
}

void HelloVK::CreateImageViews()
{
    m_swapChainImageViews.resize(m_swapChainImages.size());
    for (size_t i = 0; i < m_swapChainImages.size(); ++i) {
        VkImageViewCreateInfo createInfo{};
        createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        createInfo.image = m_swapChainImages[i];
        createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
        createInfo.format = m_swapChainImageFormat;
        createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        createInfo.subresourceRange.baseMipLevel = 0;
        createInfo.subresourceRange.levelCount = 1;
        createInfo.subresourceRange.baseArrayLayer = 0;
        createInfo.subresourceRange.layerCount = 1;
        
        VkResult result = vkCreateImageView(m_device, &createInfo, nullptr, &m_swapChainImageViews[i]);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateImageView completed successfully for image %zu", i);
        } else {
            GOLOGE("vkCreateImageView failed with error: %d for image %zu", result, i);
        }
    }
}

void HelloVK::Acquire(VkSemaphore acquire)
{
    VkResult const result = vkAcquireNextImageKHR(m_device, m_swapChain, std::numeric_limits<uint64_t>::max(), acquire,
        VK_NULL_HANDLE, &m_imageIndex);
    if (result == VK_SUCCESS) {
        if (!s_loggedAcquireNextImage) {
            GOLOGW("vkAcquireNextImageKHR completed successfully");
            s_loggedAcquireNextImage = true;
        }
        return;
    }

    if (result != VK_ERROR_OUT_OF_DATE_KHR) {
        GOLOGE("Unexpected acquire result: %d", result);
        return;
    }

    RecreateSwapChain();

    VkResult retryResult = vkAcquireNextImageKHR(m_device, m_swapChain, std::numeric_limits<uint64_t>::max(), acquire, VK_NULL_HANDLE,
        &m_imageIndex);
    if (retryResult == VK_SUCCESS) {
        GOLOGW("vkAcquireNextImageKHR (retry) completed successfully");
    } else {
        GOLOGE("vkAcquireNextImageKHR (retry) failed with error: %d", retryResult);
    }
}

void HelloVK::Present(VkPresentInfoKHR const &presentInfo)
{
    VkResult const result = vkQueuePresentKHR(m_presentQueue, &presentInfo);
    if (result == VK_SUCCESS) {
        if (!s_loggedQueuePresent) {
            GOLOGW("vkQueuePresentKHR completed successfully");
            s_loggedQueuePresent = true;
        }
        return;
    }

    if (result == VK_SUBOPTIMAL_KHR) {
        GOLOGW("vkQueuePresentKHR returned VK_SUBOPTIMAL_KHR");
        m_orientationChanged = true;
        return;
    }

    if (result == VK_ERROR_OUT_OF_DATE_KHR) {
        GOLOGW("vkQueuePresentKHR returned VK_ERROR_OUT_OF_DATE_KHR");
        RecreateSwapChain();
        return;
    }

    GOLOGE("Unexpected present result: %d", result);
}

void HelloVK::FGInitDevice()
{
    OHTestApp::Device::Instance().Init(OHTestApp::Device::DeviceDescriptor()
        .Name("Device")
        .Instance(m_instance)
        .PhysicalDevice(m_physicalDevice)
        .LogicalDevice(m_device)
        .QueueFamilyIndex(0)
        .Queue(m_graphicsQueue));
}

void HelloVK::FGCreateColorResources()
{
    m_sceneColor.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Scene Color")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(m_swapChainImageFormat)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_sceneColor.GetNativeImageView();

    m_predictedColor.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Predicted Color")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(m_swapChainImageFormat)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_predictedColor.GetNativeImageView();
}

void HelloVK::FGDestroyColorResources()
{
    m_sceneColor.Destroy();
    m_predictedColor.Destroy();
}

void HelloVK::FGCreateDepthResources()
{
    VkFormat const format = OHTestApp::Device::Instance().FindDepthFormat();

    m_sceneDepthStencil.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Scene Depth/Stencil")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(format)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_sceneDepthStencil.GetNativeImageView(format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
}

void HelloVK::CreateCommandPoolResources(const VkSemaphoreCreateInfo &semaphoreInfo,
    VkCommandPoolCreateInfo const &poolInfo, const VkFenceCreateInfo &fenceInfo,
    VkCommandBufferAllocateInfo &commandBufferAllocateInfo)
{
    for (uint32_t i = 0U; i < OHTestApp::FRAMES_IN_FLIGHT; ++i) {
        FrameInFlight &fif = m_framesInFlights[static_cast<size_t>(i)];
        
        VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &fif.acquire);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateSemaphore (acquire) completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateSemaphore (acquire) failed with error: %d for frame %u", result, i);
            return;
        }

        result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &fif.commandPool);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateCommandPool completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateCommandPool failed with error: %d for frame %u", result, i);
            return;
        }

        commandBufferAllocateInfo.commandPool = fif.commandPool;
        result = vkAllocateCommandBuffers(m_device, &commandBufferAllocateInfo, &fif.commandBuffer);
        if (result == VK_SUCCESS) {
            GOLOGW("vkAllocateCommandBuffers completed successfully for frame %u", i);
        } else {
            GOLOGE("vkAllocateCommandBuffers failed with error: %d for frame %u", result, i);
            return;
        }

        char label[256U];
        
        // 使用安全的 snprintf 替换 snprintf_s
        int iRet = std::snprintf(label, sizeof(label), "FiF #%u", i);
        if (iRet < 0 || static_cast<size_t>(iRet) >= sizeof(label)) {
            // 格式化失败或缓冲区不足，使用默认标签
            std::strncpy(label, "FrameInFlight", sizeof(label) - 1);
            label[sizeof(label) - 1] = '\0';  // 确保以null结尾
            GOLOGE("snprintf failed or buffer too small for FiF #%u", i);
        }
        
        OHTestApp::SetLabel(m_device, fif.commandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, label);

        result = vkCreateFence(m_device, &fenceInfo, nullptr, &fif.fence);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateFence completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateFence failed with error: %d for frame %u", result, i);
            return;
        }
    }
}

void HelloVK::FGCreateCommandPool()
{
    OHTestApp::CommandPool::Instance().Init(OHTestApp::CommandPool::CommandPoolDescriptor()
        .Name("CommandPool")
        .Device(m_device)
        .Flags(0U)
        .QueueFamilyIndex(OHTestApp::Device::Instance().GetQueueFamilyIndex())
        .Queue(OHTestApp::Device::Instance().GetNativeQueue()));

    constexpr VkSemaphoreCreateInfo semaphoreInfo {
        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U
    };

    VkCommandPoolCreateInfo const poolInfo {
        .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
        .pNext = nullptr,
        .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
        .queueFamilyIndex = OHTestApp::Device::Instance().GetQueueFamilyIndex()
    };

    constexpr VkFenceCreateInfo fenceInfo {
        .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
        .pNext = nullptr,
        .flags = VK_FENCE_CREATE_SIGNALED_BIT
    };

    VkCommandBufferAllocateInfo commandBufferAllocateInfo {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
        .pNext = nullptr,
        .commandPool = VK_NULL_HANDLE,
        .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
        .commandBufferCount = 1U
    };

    m_framesInFlights.clear();
    m_framesInFlights.resize(OHTestApp::FRAMES_IN_FLIGHT);
    m_writingCommandBufferIdx = 0U;

    CreateCommandPoolResources(semaphoreInfo, poolInfo, fenceInfo, commandBufferAllocateInfo);
}

void HelloVK::FGCreateSwapchainSyncObjects()
{
    size_t const count = m_swapChainImages.size();
    m_swapchainInfo.clear();
    m_swapchainInfo.resize(count);

    constexpr VkSemaphoreCreateInfo semaphoreInfo {
        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U
    };

    for (size_t i = 0; i < count; ++i) {
        auto &info = m_swapchainInfo[i];
        VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &info.renderEnd);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateSemaphore (renderEnd) completed successfully for swapchain image %zu", i);
        } else {
            GOLOGE("vkCreateSemaphore (renderEnd) failed with error: %d for swapchain image %zu", result, i);
            return;
        }
    }
}


void HelloVK::FGInitMainSceneRenderer()
{
    OHTestApp::MainSceneRenderer &sceneRenderer = OHTestApp::MainSceneRenderer::Instance();

    sceneRenderer.Init(OHTestApp::MainSceneRenderer::MainSceneRendererDescriptor {
        .frameInFlightNum = OHTestApp::FRAMES_IN_FLIGHT,
        .frameBufferNum = OHTestApp::FRAMES_IN_FLIGHT,
        .frameBufferWidth = m_swapChainExtent.width,
        .frameBufferHeight = m_swapChainExtent.height,
        .colorFormat = m_sceneColor.GetFormat(),
        .depthStencilFormat = m_sceneDepthStencil.GetFormat()
    });

    VkImageView const attachments[] = {m_sceneColor.GetNativeImageView(), m_sceneDepthStencil.GetNativeImageView()};

    VkFramebufferCreateInfo framebufferInfo {
        .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U,
        .renderPass = sceneRenderer.GetRenderPass(),
        .attachmentCount = static_cast<uint32_t>(std::size(attachments)),
        .pAttachments = attachments,
        .width = m_swapChainExtent.width,
        .height = m_swapChainExtent.height,
        .layers = 1U
    };

    VkResult result = vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &m_sceneFramebuffer);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateFramebuffer completed successfully");
    } else {
        GOLOGE("vkCreateFramebuffer failed with error: %d", result);
    }
}



void HelloVK::FGDestroyMainSceneRenderer()
{
    OHTestApp::MainSceneRenderer::Instance().Destroy();
}

void HelloVK::RenderAndUpdateCameraInfo(OHTestApp::MainSceneRenderer &sceneRenderer, FrameInFlight *fif,
    uint8_t fifIndex)
{
    sceneRenderer.Render(fif->commandBuffer, m_sceneFramebuffer, static_cast<size_t>(fifIndex));

    m_viewProj = sceneRenderer.GetSceneViewProjMatrix();
    m_invViewProj = glm::inverse(sceneRenderer.GetSceneViewProjMatrix());
}

void HelloVK::FGBalancedInterRender()
{

    if (!m_window) {
        return;
    }

    if (m_orientationChanged) {
        OnOrientationChange();
    }

    auto const fifIndex = static_cast<uint8_t>(m_writingCommandBufferIdx);
    FrameInFlight *fif = &m_framesInFlights[m_writingCommandBufferIdx];
    UpdateWritingCommandBufferIdx();

    VkResult result = vkWaitForFences(m_device, 1U, &fif->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
    if (result == VK_SUCCESS) {
        if (!s_loggedWaitForFences) {
            GOLOGW("vkWaitForFences completed successfully");
            s_loggedWaitForFences = true;
        }
    } else {
        GOLOGE("vkWaitForFences failed with error: %d", result);
    }

    ResetStatus(fif);

    VkCommandBufferBeginInfo beginCB = CreateBeginInfo();
    result = vkBeginCommandBuffer(fif->commandBuffer, &beginCB);
    if (result == VK_SUCCESS) {
        if (!s_loggedBeginCommandBuffer) {
            GOLOGW("vkBeginCommandBuffer completed successfully");
            s_loggedBeginCommandBuffer = true;
        }
    } else {
        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
    }

    OHTestApp::MainSceneRenderer &sceneRenderer = OHTestApp::MainSceneRenderer::Instance();
    sceneRenderer.Update(static_cast<uint32_t>(fifIndex));


    // 标准渲染流程：只渲染场景
    RenderAndUpdateCameraInfo(sceneRenderer, fif, fifIndex);

    // 将离屏的 Scene Color 拷贝到当前 swapchain 图像
    {
        VkCommandBuffer cmd = fif->commandBuffer;

        // 源图像：场景颜色贴图（离屏）
        VkImage srcImage = m_sceneColor.GetNativeImage(); // 需存在该接口
        // 目标图像：当前 swapchain 图像
        VkImage dstImage = m_swapChainImages[m_imageIndex];

        // 1) 布局转换：Scene Color -> TRANSFER_SRC_OPTIMAL，Swapchain -> TRANSFER_DST_OPTIMAL
        VkImageMemoryBarrier barriers[2]{};

        // Scene Color: SHADER_READ_ONLY_OPTIMAL -> TRANSFER_SRC_OPTIMAL
        barriers[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
        barriers[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
        barriers[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
        barriers[0].oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
        barriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
        barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barriers[0].image = srcImage;
        barriers[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        barriers[0].subresourceRange.baseMipLevel = 0;
        barriers[0].subresourceRange.levelCount = 1;
        barriers[0].subresourceRange.baseArrayLayer = 0;
        barriers[0].subresourceRange.layerCount = 1;

        // Swapchain: UNDEFINED(丢弃旧内容) -> TRANSFER_DST_OPTIMAL
        barriers[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
        barriers[1].srcAccessMask = 0;
        barriers[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
        barriers[1].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; // 丢弃先前内容，适配首帧与任意状态
        barriers[1].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
        barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barriers[1].image = dstImage;
        barriers[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        barriers[1].subresourceRange.baseMipLevel = 0;
        barriers[1].subresourceRange.levelCount = 1;
        barriers[1].subresourceRange.baseArrayLayer = 0;
        barriers[1].subresourceRange.layerCount = 1;

        vkCmdPipelineBarrier(cmd,
            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // src
            VK_PIPELINE_STAGE_TRANSFER_BIT,                // dst
            0,
            0, nullptr,
            0, nullptr,
            2, barriers);

        // 2) 拷贝：Scene Color -> Swapchain
        VkImageCopy region{};
        region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        region.srcSubresource.mipLevel = 0;
        region.srcSubresource.baseArrayLayer = 0;
        region.srcSubresource.layerCount = 1;
        region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        region.dstSubresource.mipLevel = 0;
        region.dstSubresource.baseArrayLayer = 0;
        region.dstSubresource.layerCount = 1;
        region.srcOffset = {0, 0, 0};
        region.dstOffset = {0, 0, 0};
        region.extent = { m_swapChainExtent.width, m_swapChainExtent.height, 1 };

        vkCmdCopyImage(cmd,
            srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
            dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
            1, &region);

        // 3) 布局恢复：Scene Color 回到 SHADER_READ_ONLY_OPTIMAL；Swapchain -> PRESENT_SRC_KHR
        barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
        barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
        barriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
        barriers[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

        barriers[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
        barriers[1].dstAccessMask = 0;
        barriers[1].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
        barriers[1].newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

        vkCmdPipelineBarrier(cmd,
            VK_PIPELINE_STAGE_TRANSFER_BIT,               // src
            VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,         // dst
            0,
            0, nullptr,
            0, nullptr,
            2, barriers);
    }

    result = vkEndCommandBuffer(fif->commandBuffer);
    if (result == VK_SUCCESS) {
        if (!s_loggedEndCommandBuffer) {
            GOLOGW("vkEndCommandBuffer completed successfully");
            s_loggedEndCommandBuffer = true;
        }
    } else {
        GOLOGE("vkEndCommandBuffer failed with error: %d", result);
    }

    InterRealFrameDisplay(fif);
}

VkSubmitInfo HelloVK::CreateSubmitInfo(FrameInFlight *fif, const VkPipelineStageFlags &waitStage)
{
    VkSubmitInfo submitInfo{};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.waitSemaphoreCount = 1U;
    submitInfo.pWaitSemaphores = &fif->acquire;
    submitInfo.pWaitDstStageMask = &waitStage;
    submitInfo.commandBufferCount = 1U;
    submitInfo.pCommandBuffers = &fif->commandBuffer;
    submitInfo.signalSemaphoreCount = 1U;
    submitInfo.pSignalSemaphores = &m_swapchainInfo[m_imageIndex].renderEnd;
    return submitInfo;
}

VkPresentInfoKHR HelloVK::CreatePresentInfo(VkResult &presentResult)
{
    VkPresentInfoKHR presentInfo{};
    presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    presentInfo.waitSemaphoreCount = 1U;
    presentInfo.pWaitSemaphores = &m_swapchainInfo[m_imageIndex].renderEnd;
    presentInfo.swapchainCount = 1U;
    presentInfo.pSwapchains = &m_swapChain;
    presentInfo.pImageIndices = &m_imageIndex;
    presentInfo.pResults = &presentResult;
    return presentInfo;
}

void HelloVK::InterRealFrameDisplay(FrameInFlight *fif)
{
    // 标准Vulkan显示流程
    constexpr VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    
    VkSubmitInfo const submitInfo = CreateSubmitInfo(fif, waitStage);
    VkResult result = vkQueueSubmit(m_graphicsQueue, 1U, &submitInfo, fif->fence);
    if (result == VK_SUCCESS) {
        if (!s_loggedQueueSubmit) {
            GOLOGW("vkQueueSubmit completed successfully");
            s_loggedQueueSubmit = true;
        }
    } else {
        GOLOGE("vkQueueSubmit failed with error: %d", result);
    }

    VkResult presentResult = VK_SUCCESS;
    VkPresentInfoKHR const presentInfo = CreatePresentInfo(presentResult);
    Present(presentInfo);
}

void HelloVK::UpdateWritingCommandBufferIdx()
{
    m_writingCommandBufferIdx = (m_writingCommandBufferIdx + 1U) % OHTestApp::FRAMES_IN_FLIGHT;
}

VkCommandBufferBeginInfo HelloVK::CreateBeginInfo()
{
    VkCommandBufferBeginInfo beginInfo{};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    return beginInfo;
}

void HelloVK::ResetStatus(FrameInFlight *fif)
{
    VkResult result = vkResetFences(m_device, 1U, &fif->fence);
    if (result == VK_SUCCESS) {
        if (!s_loggedResetFences) {
            GOLOGW("vkResetFences completed successfully");
            s_loggedResetFences = true;
        }
    } else {
        GOLOGE("vkResetFences failed with error: %d", result);
    }
    
    result = vkResetCommandPool(m_device, fif->commandPool, 0U);
    if (result == VK_SUCCESS) {
        if (!s_loggedResetCommandPool) {
            GOLOGW("vkResetCommandPool completed successfully");
            s_loggedResetCommandPool = true;
        }
    } else {
        GOLOGE("vkResetCommandPool failed with error: %d", result);
    }
    
    Acquire(fif->acquire);
}

void HelloVK::ResetStatus(FrameInFlight *fif, VkCommandBufferBeginInfo &beginCB)
{
    ResetStatus(fif);
    
    VkResult result = vkBeginCommandBuffer(fif->commandBuffer, &beginCB);
    if (result == VK_SUCCESS) {
        if (!s_loggedBeginCommandBuffer) {
            GOLOGW("vkBeginCommandBuffer completed successfully");
            s_loggedBeginCommandBuffer = true;
        }
    } else {
        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
    }
}


} // namespace vkt